package cn.swust.score.service.impl;

import cn.swust.score.dao.CandidateDao;
import cn.swust.score.dao.CandidateStagInfoDao;
import cn.swust.score.dao.GradeDao;
import cn.swust.score.dao.RaterDao;
import cn.swust.score.dao.StageDao;
import cn.swust.score.pojo.Candidate;
import cn.swust.score.pojo.Grade;
import cn.swust.score.pojo.QueryCandidate;
import cn.swust.score.pojo.Rater;
import cn.swust.score.pojo.StageGrade;
import cn.swust.score.service.CandidateStagInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal; 
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

@Service
public class CandidateStagInfoServiceImpl implements CandidateStagInfoService {

	@Autowired
	CandidateStagInfoDao candidateStagInfoDao;

	@Autowired
	RaterDao raterDao;

	@Autowired
	CandidateDao candidateDao;

	@Autowired
	GradeDao gradeDao;

	@Autowired
	StageDao stageDao;

	@Override
	public int delById(Integer stageId, Integer candidateId) {
		return candidateStagInfoDao.delById(candidateId, stageId);
	}

	@Override
	public int save(StageGrade record) {
		return candidateStagInfoDao.save(record);
	}

	@Override
	public StageGrade getById(Integer stageId, Integer candidateId) {
		return candidateStagInfoDao.getById(candidateId, stageId);
	}

	@Override
	public int editById(StageGrade record) {
		return candidateStagInfoDao.editById(record);
	}

	@Override
	public List<StageGrade> getByStageId(int stageId) {
		return candidateStagInfoDao.getByStageId(stageId);
	}

	@Override
	public List<StageGrade> list() {
		return candidateStagInfoDao.list();
	}

	public boolean checkScore(int stageId, int raterId) {
		Integer scoreInfoId = stageDao.getScoreIdById(stageId);
		Rater rater = raterDao.getById(raterId);
		int countScore = candidateDao.countScore(scoreInfoId, rater.getSchool());
		int countGrade = gradeDao.countGrade(raterId, stageId);
		if (countScore != countGrade)
			return false;
		else
			return true;
	}

	@Transactional
	@Override
	public int commitRaterScore(int stageId, int raterId) {
		if (!checkScore(stageId, raterId)) {
			return 1; // 成绩没有打完
		}
		gradeDao.updataSetAllVerify(raterId, stageId);

		// 获取所有已经打分确认的阶段成绩;
		List<Grade> listAll = gradeDao.getVerifyByStageId(stageId);

		// 遍历;
		// 获得candidateId序列;
		int preCandidate = 0;
		int max = 0, min = 0;
		int count = 0;
		double sum = 0.0;
		double average = 0.0;
		List<StageGrade> stageGrades = new ArrayList<StageGrade>();
		for (int i = 0; i < listAll.size(); i++) {

			Grade grade = listAll.get(i);
			if (preCandidate != grade.getCandidateId()) {
				// 处理上一个候选者;
				if (i != 0) {
					if (count > 2) {
						sum -= min;
						sum -= max;
						average = sum / (count - 2);

					} else {
						average = sum / count;
					}

					BigDecimal bg = new BigDecimal(average);
					double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

					System.out.println(f1);
					StageGrade sg = new StageGrade();
					sg.setCandidateId(preCandidate);
					BigDecimal maxbg = new BigDecimal(max);
					sg.setHighestScore(maxbg);
					BigDecimal minbg = new BigDecimal(min);
					sg.setLowestScore(minbg);
					BigDecimal averagebg = new BigDecimal(f1);
					sg.setAverage(averagebg);
					sg.setStageId(stageId);
					stageGrades.add(sg); 
				}

				count = 1;
				max = grade.getFraction();
				min = grade.getFraction();
				sum = grade.getFraction();
				preCandidate = grade.getCandidateId();
			} else {
				sum += grade.getFraction();
				count ++ ;
				if (max < grade.getFraction())
					max = grade.getFraction();
				if (min > grade.getFraction())
					min = grade.getFraction();
			}
		}

		BigDecimal bg = new BigDecimal(average);
		double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

		System.out.println(f1);
		StageGrade sg = new StageGrade();
		sg.setCandidateId(preCandidate);
		BigDecimal maxbg = new BigDecimal(max);
		sg.setHighestScore(maxbg);
		BigDecimal minbg = new BigDecimal(min);
		sg.setLowestScore(minbg);
		BigDecimal averagebg = new BigDecimal(f1);
		sg.setAverage(averagebg);
		sg.setStageId(stageId);
		stageGrades.add(sg);

		Collections.sort(stageGrades, new Comparator<StageGrade>() {
			public int compare(StageGrade o1, StageGrade o2) {
				return Double.compare(o2.getAverage().doubleValue(), o1.getAverage().doubleValue());
			}
		});

		// 处理重复排名
		BigDecimal preScore = new BigDecimal(0.0);
		int preRank = 0;
		for (int i = 0; i < stageGrades.size(); i++) {
			sg = stageGrades.get(i);

			if (Double.doubleToLongBits(preScore.doubleValue()) != Double
					.doubleToLongBits(sg.getAverage().doubleValue())) {
				preScore = sg.getAverage();
				sg.setStageRanking(i + 1);
				preRank = i + 1;
			} else {
				sg.setStageRanking(preRank);
			}

			candidateStagInfoDao.save(sg);
		}
		Integer scoreInfoId = stageDao.getScoreIdById(stageId);
		setRanking(scoreInfoId);
		return 0;
	}
	@Override
	public void setRanking(int scoreInfoId) {
		QueryCandidate param = new QueryCandidate();
		param.setScoreInfoId(scoreInfoId);
		List<Candidate> list = candidateDao.list(param);
		for (int i = 0; i < list.size(); i++) {
			Candidate c = list.get(i);
			Double score1 = gradeDao.getStageScore(c.getId(), 1);
			Double score2 = gradeDao.getStageScore(c.getId(), 2);
			if (score1 == null)
				score1 = 0.0;
			if (score2 == null)
				score2 = 0.0;
			double totalScore = (c.getInitialScore1().doubleValue()
					+ (double) c.getInitialScore2().doubleValue()) * 0.20 + (score1  + score2) * 0.3;
			c.setTotalScore(totalScore);
		}

		Collections.sort(list, new Comparator<Candidate>() {
			public int compare(Candidate o1, Candidate o2) {
				return Double.compare(o2.getTotalScore().doubleValue(), o1.getTotalScore().doubleValue());
			}
		});

		// 处理重复排名
		BigDecimal preScore = new BigDecimal(0.0);
		int preRank = 0;
		for (int i = 0; i < list.size(); i++) {
			Candidate c = list.get(i);
			if (Double.doubleToLongBits(preScore.doubleValue()) != Double
					.doubleToLongBits(c.getTotalScore().doubleValue())) {
				preRank = i + 1;
			} else {
				c.setRanking(preRank);
			} 
			candidateDao.editRankById(c);
		}

	}
}
